﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

namespace GomokuClient
{
    public partial class Form1 : Form
    {
        private byte[] byteData = new byte[1024];

        private byte[] btest = new byte[225];

        private Stopwatch TotalTime = new Stopwatch();

        private byte MyID = 0;
        private bool ItsYourTurn = false;

        public Form1()
        {
            InitializeComponent();
        }

        public Socket clientSocket;

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPAddress ipAddress = IPAddress.Parse(comboBox1.Text);
                //Server is listening on port 1000
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 999);

                //Connect to the server
                clientSocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);
                button1.Enabled = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void MensagemRecebida(IAsyncResult ar)
        {
            try
            {
                clientSocket.EndReceive(ar);
                ProtocolMessage msgReceived = new ProtocolMessage(byteData);
                switch (msgReceived.Cmd)
                {
                    case ProtocolMessage.Command.InsertPiece:

                        break;
                    case ProtocolMessage.Command.RefreshBoard:
                        ConvertDataBoard(msgReceived.BoardData);
                        break;
                    case ProtocolMessage.Command.ItsYourTurn:
                        ItsYourTurn = true;
                        label2.Text = "Jogue, é a sua vez";
                        panel1.Cursor = Cursors.Hand;
                        break;
                    case ProtocolMessage.Command.EndOfGame:
                        //FinalizaPartida();
                        ItsYourTurn = false;
                        switch (msgReceived.MatchResult)
                        {
                            case 0:
                                label2.Text = "Você perdeu!";
                                label2.BackColor = Color.Red;
                                DrawVictory(msgReceived.WinInformation, new Pen(Color.Red, 5));
                                break;
                            case 1:
                                label2.Text = "Você ganhou!";
                                label2.BackColor = Color.Green;
                                DrawVictory(msgReceived.WinInformation, new Pen(Color.Lime, 5));
                                break;
                            case 3:
                                label2.Text = "Adversário fugiu!";
                                label2.BackColor = Color.Yellow;
                                break;
                            default:
                                break;
                        }
       
                        ItsYourTurn = false;
                        
                        break;
                    case ProtocolMessage.Command.IwantPlay:

                        break;
                    case ProtocolMessage.Command.TextInformation:
                        label2.Text = msgReceived.TextMessage;
                        break;
                    case ProtocolMessage.Command.ConnectionResponse:
                        TotalTime.Start();
                        if (msgReceived.ConnStatus == ProtocolMessage.ConnectionStatus.FullRoom)
                        {
                            MessageBox.Show("A sala está cheia, tente mais tarde");
                        }
                        else if (msgReceived.ConnStatus == ProtocolMessage.ConnectionStatus.WelcomeAboard)
                        {
                            msgToSend.MyID = msgReceived.MyID;
                            IniciarPartida();
                        }
                        break;
                    default:
                        break;
                }
                clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(MensagemRecebida), clientSocket);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Servidor Gomoku", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private void OnConnect(IAsyncResult ar)
        {
            try
            {
                clientSocket.EndConnect(ar);

                //Fill the info for the message to be send
                ProtocolMessage msgToSend = new ProtocolMessage();

                msgToSend.Cmd = ProtocolMessage.Command.IwantPlay;

                byte[] b = msgToSend.ToByte();

                //Send the message to the server
                clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
                clientSocket.BeginReceive(byteData,
                           0,
                           byteData.Length,
                           SocketFlags.None,
                           new AsyncCallback(MensagemRecebida),
                           null);
            }
            catch (Exception ex)
            {
                button1.Enabled = true;
                MessageBox.Show("Verifique se o servidor está online");
                //MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
        }

        private void IniciarPartida()
        {
            pictureBox1.Image = GomokuClient.Properties.Resources.Fundo;

        }

        private void FinalizaPartida()
        {
            pictureBox1.Image = GomokuClient.Properties.Resources.FundoOff;

        }


        private void OnSend(IAsyncResult ar)
        {
            try
            {
                clientSocket.EndSend(ar);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            string strIP = null;

            IPHostEntry HosyEntry = Dns.GetHostEntry((Dns.GetHostName()));
            if (HosyEntry.AddressList.Length > 0)
            {
                foreach (IPAddress ip in HosyEntry.AddressList)
                {
                    strIP = ip.ToString();
                    comboBox1.Items.Add(strIP);
                }
            }

        }

        int x = 0, y = 0;
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (ItsYourTurn)
            {
                if (e.X > 33)
                {
                    x = 0;
                    for (int i = 33; i < 510; i += 33)
                    {
                        if (e.X > i && e.X < i + 20)
                        {
                            x = (i / 33);
                            break;
                        }
                    }
                }

                if (e.Y > 27)
                {
                    y = 0;
                    for (int i = 29; i < 470; i += 31)
                    {
                        if (e.Y > i && e.Y < i + 20)
                        {
                            y = (i / 29);
                            break;
                        }
                    }
                }

                if (y > 0 && x > 0)
                {
                    panel1.Cursor = Cursors.Hand;
                }
                else
                {
                    panel1.Cursor = Cursors.No;
                }
            }
            else
            {
                panel1.Cursor = Cursors.WaitCursor;
            }
        }

        ProtocolMessage msgToSend = new ProtocolMessage();
        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (ItsYourTurn)
            {
                if (y != 0 && x != 0)
                {
                    ItsYourTurn = false;
                    msgToSend.Cmd = ProtocolMessage.Command.InsertPiece;
                    msgToSend.XCoordinate = (byte)x;
                    msgToSend.YCoordinate = (byte)y;
                    byte[] b = msgToSend.ToByte();
                    clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSend), null);

                    label2.Text = "Aguarde a jogada do seu adversário";
                    TotalTime.Stop();
                }
            }
        }

        byte[] MyBoardData = new byte[225];

        private void DrawVictory(ProtocolMessage.WinInform wi, Pen p)
        {
            //pictureBox1.Image = GomokuClient.Properties.Resources.Fundo;
            Bitmap tmp = new Bitmap(pictureBox1.Image.Width, pictureBox1.Image.Height);
            Graphics grPhoto = Graphics.FromImage(tmp);

            grPhoto.DrawImage(pictureBox1.Image, new Rectangle(0, 0, tmp.Width, tmp.Height), 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel);
            float x = (float)(((float)wi.x * 40.5))+16;
            int y = (wi.y * 41) + 16;
            switch (wi.direction)
            {
                case ProtocolMessage.WinDirection.Vertical:
                    grPhoto.DrawLine(p, new Point((int)x, (int)y), new Point((int)(x - 162), (int)y));
                    break;
                case ProtocolMessage.WinDirection.Horizontal:
                    grPhoto.DrawLine(p, new Point((int)x, (int)y), new Point((int)x, (int)(y + 164)));
                    break;
                case ProtocolMessage.WinDirection.DiagonalToRight:
                    grPhoto.DrawLine(p, new Point((int)x, (int)y), new Point((int)(x+162), (int)(y - 164)));

                    break;
                case ProtocolMessage.WinDirection.DiagonalToLeft:
                    grPhoto.DrawLine(p, new Point((int)x, (int)y), new Point((int)(x + 162), (int)(y + 164)));
                    break;
                default:
                    break;
            }

            pictureBox1.Image = tmp;
        }

    

        private void ConvertDataBoard(byte[] BoardData)
        {
            //pictureBox1.Image = GomokuClient.Properties.Resources.Fundo;
            Bitmap tmp = new Bitmap(pictureBox1.Image.Width, pictureBox1.Image.Height);
            Graphics grPhoto = Graphics.FromImage(tmp);

            grPhoto.DrawImage(GomokuClient.Properties.Resources.Fundo, new Rectangle(0, 0, tmp.Width, tmp.Height), 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel);

            if (BoardData.Length == 225)
            {
                int x = 1, y = 1;
                for (int i = 0; i < BoardData.Length; i++)
                {
                    if (BoardData[i] != 0)
                    {
                        if (BoardData[i] == 1)
                        {
                            if (MyBoardData[i] == BoardData[i])
                            {
                                grPhoto.DrawImage(imageList1.Images[0], (float)((float)x * 40.5), y * 41);
                            }
                            else
                            {
                                grPhoto.DrawImage(imageList1.Images[2], (float)((float)x * 40.5), y * 41);
                            }
                        }
                        else
                        {
                            if (MyBoardData[i] == BoardData[i])
                            {
                                grPhoto.DrawImage(imageList1.Images[1], (float)((float)x * 40.5), y * 41);
                            }
                            else
                            {
                                grPhoto.DrawImage(imageList1.Images[3], (float)((float)x * 40.5), y * 41);
                            }
                        }
                        MyBoardData[i] = BoardData[i];
                    }
                    x++;
                    if (x > 15)
                    {
                        x = 1;
                        y++;
                        if (y > 15)
                        {
                            break;
                        }
                    }
                }
                pictureBox1.Image = tmp;
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (msgToSend.MyID != 0)
            {
                msgToSend.Cmd = ProtocolMessage.Command.EndOfGame;
                msgToSend.MatchResult = 3;
                byte[] b = msgToSend.ToByte();
                clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
            }
            if (clientSocket!= null)
            {
             
            clientSocket.Close();   
            }
        }
    }
}
